﻿using Easy.Common.Params;
using Easy.Services.DbContexts;
using Easy.Services.Entities;
using Microsoft.EntityFrameworkCore;
using MySql.Data.MySqlClient;
using System.Linq.Expressions;

namespace Easy.Services.Core
{
    /// <summary>
    /// BaseService
    /// </summary>
    public partial class BaseService<T> where T : BaseEntity
    {
        #region constructor

        readonly MySQLDbContext context;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="_context"></param>
        public BaseService(MySQLDbContext _context)
        {
            this.context = _context;

        }

        #endregion

        #region base sync method

        /// <summary>
        /// 获取所有数据
        /// </summary>
        /// <param name="includeDelete">是否包含软删除数据false不包含true包含软删除</param>
        /// <param name="isTracking">是否追踪</param>
        /// <returns>返回结果</returns>
        public IQueryable<T> GetAll(bool includeDelete = false, bool isTracking = false)
        {
            if (includeDelete)
            {
                if (isTracking)
                {
                    return context.Set<T>().OrderBy(c => c.Id).AsNoTracking();
                }
                return context.Set<T>().OrderBy(c => c.Id);
            }
            else
            {
                if (isTracking)
                {
                    return context.Set<T>().OrderBy(c => c.Id).Where(e => e.IsDelete == false).AsNoTracking();
                }
                return context.Set<T>().OrderBy(c => c.Id).Where(e => e.IsDelete == false);
            }
        }

        /// <summary>
        /// 获取集合数据
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public List<T> GetList(Expression<Func<T, bool>> expression = null)
        {
            if (expression == null)
            {
                return GetAll().ToList();
            }
            return GetAll().Where(expression).ToList();
        }


        /// <summary>
        /// 获取总条数
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <param name="includeDelete">是否包含软删除数据false不包含true包含软删除</param>
        /// <returns>返回结果</returns>
        public long GetTotalCount(Expression<Func<T, bool>> whereExpression = null, bool includeDelete = false)
        {
            if (whereExpression == null)
            {

                return GetAll(includeDelete).AsNoTracking().LongCount();
            }
            else
            {
                return GetAll(includeDelete).Where(whereExpression).AsNoTracking().LongCount();
            }
        }


        public List<T> GetPage(PageParam page, Expression<Func<T, bool>> whereExpression = null, bool includeDelete = false)
        {
            if (whereExpression == null)
            {
                return GetAll(includeDelete).AsNoTracking().Skip((page.Page - 1) * page.PageSize).Take(page.PageSize).ToList();
            }
            else
            {
                return GetAll(includeDelete).Where(whereExpression).AsNoTracking().Skip((page.Page - 1) * page.PageSize).Take(page.PageSize).ToList();
            }

        }

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="expression">expression</param>
        /// <param name="includeDelete">是否包含软删除数据</param>
        /// <returns>返回结果</returns>
        public T GetBase(Expression<Func<T, bool>> expression, bool includeDelete = false)
        {
            if (expression == null)
            {
                return GetAll(includeDelete, true).OrderBy(c => c.Id).FirstOrDefault();
            }
            return GetAll(includeDelete, true).Where(expression).OrderBy(c => c.Id).FirstOrDefault();
        }

        /// <summary>
        /// 新建实体
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns>返回结果</returns>
        public long AddBase(T entity)
        {
            context.Set<T>().Add(entity);
            var result = context.SaveChanges();
            if (result != 1 || entity.Id <= 0)
            {
                throw new Exception("entity written to the database fail");
            }
            return entity.Id;
        }

        /// <summary>
        /// 批量新建实体
        /// </summary>
        /// <param name="list">实体集合</param>
        public bool AddBatchBase(List<T> list)
        {
            context.Set<T>().AddRange(list);
            var result = context.SaveChanges();
            return list.Count == result;
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity">实体</param>
        public bool UpdateBase(T entity)
        {
            entity.EditDate = DateTime.UtcNow;
            context.Set<T>().Update(entity);
            var result = context.SaveChanges();
            return result == 1;
        }

        /// <summary>
        /// 批量更新实体
        /// </summary>
        /// <param name="list">实体集合</param>
        public bool UpdateBatchBase(List<T> list)
        {
            context.Set<T>().UpdateRange(list);
            var result = context.SaveChanges();
            return list.Count == result;
        }

        /// <summary>
        /// 软删除实体
        /// </summary>
        /// <param name="entity">实体</param>
        public bool DeleteBase(T entity)
        {
            entity.IsDelete = true;
            entity.EditDate = DateTime.UtcNow;
            context.Set<T>().Update(entity);
            var result = context.SaveChanges();
            return result == 1;
        }
        /// <summary>
        /// 批量软删除实体
        /// </summary>
        /// <param name="list">实体集合</param>
        public bool DeleteBatchBase(List<T> list)
        {
            foreach (var item in list)
            {
                item.IsDelete = true;
                item.EditDate = DateTime.UtcNow;
            }
            context.Set<T>().UpdateRange(list);
            var result = context.SaveChanges();
            return list.Count == result;
        }

        /// <summary>
        /// 获取集合
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <param name="includeDelete">是否包含软删除数据false不包含true包含软删除</param>
        /// <returns>返回结果</returns>
        public List<T> GetListBase( Expression<Func<T, bool>> whereExpression = null, bool includeDelete = false)
        {
            List<T> list;
            if (whereExpression == null)
            {
                list = [.. GetAll(includeDelete).AsNoTracking()];
            }
            else
            {
                list = [.. GetAll(includeDelete).AsNoTracking().Where(whereExpression)];
            }
            return list;
        }


        public bool Exist(Expression<Func<T, bool>> expression = null)
        {
            if (expression == null)
            {
                return GetAll().Any();
            }
            return GetAll().Any(expression);
        }

        #endregion


        #region base sync sql method

        /// <summary>
        /// 软删除数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="deleteUserId">删除者</param>
        /// <param name="id">主键</param>
        /// <returns>返回结果</returns>
        public bool DeleteBase(string tableName, long deleteUserId, long id)
        {
            DateTime deleteDate = DateTime.UtcNow;
            int row = context.Database.ExecuteSqlRaw($"UPDATE {tableName} SET IsDelete=1,DeleteUserId=@DeleteUserId,DeleteDate=@DeleteDate WHERE Id = @Id",
            [
                new MySqlParameter("DeleteUserId", deleteUserId),
                new MySqlParameter("DeleteDate", deleteDate),
                new MySqlParameter("Id", id)
            ]);
            return row == 1;
        }

        /// <summary>
        /// 软删除数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="deleteUserId">删除者</param>
        /// <param name="filed">字段</param>
        /// <param name="value">值</param>
        /// <returns>返回结果</returns>
        public bool DeleteBase(string tableName, long deleteUserId, string filed, string value)
        {
            DateTime deleteDate = DateTime.UtcNow;
            int row = context.Database.ExecuteSqlRaw($"UPDATE {tableName} SET IsDelete=1,DeleteUserId=@DeleteUserId,DeleteDate=@DeleteDate WHERE {filed} = @{filed}",
            [
                new MySqlParameter("DeleteUserId", deleteUserId),
                new MySqlParameter("DeleteDate", deleteDate),
                new MySqlParameter($"{filed}", value)
            ]);
            return row > 0;
        }
        #endregion

   
    }

}
